package com.bsg.upm.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.check.CheckResult;
import com.bsg.upm.check.ServUserCheck;
import com.bsg.upm.constant.DictConstants;
import com.bsg.upm.constant.DictTypeConstants;
import com.bsg.upm.constant.OperateDictConstants;
import com.bsg.upm.constant.OperateDictTypeConstants;
import com.bsg.upm.constant.SysConstants;
import com.bsg.upm.dto.ServUserDto;
import com.bsg.upm.entity.ServEntity;
import com.bsg.upm.entity.SubServEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;

import smlib.Resp;
import smlib.Smlib;
import smlib.User;

/**
 * 用户管理业务处理类
 * 
 * @author HCK
 *
 */
@Service
public class ServUserService extends BaseService {

	@Resource
	private ServUserCheck servUserCheck;

	/**
	 * 用户查询
	 * 
	 * @param servId
	 *            服务编码
	 * @return 操作结果
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson list(String servId) throws APIException {
		try {
			// 结果集
			JSONArray results = new JSONArray();

			// 获取指定服务
			ServEntity serv = servDao.getBase(servId);
			if (serv == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "服务不存在");
			}

			// 服务类型
			String servType = serv.getOrder().getDefinitionServ().getName();
			if (!SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
				return RespJsonFactory.build(HttpStatus.SC_BAD_REQUEST, "该类型服务无用户");
			}

			// 站点
			String siteId = serv.getOrder().getArea().getSite().getId();

			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				// 子服务类型
				String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();

				// switch_manager
				if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
					if (StringUtils.isNotBlank(subServ.getRelateId())) {
						// 从MGM获取指定服务的地址
						List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId, subServ.getRelateId(),
								subServ.getSubOrder().getDefinitionSubServ().getPortKey());

						if (ipAndPorts.size() == 0) {
							return RespJsonFactory.build(HttpStatus.SC_GONE, "获取不到SWM地址");
						}

						Resp resp = null;
						for (Map<String, Object> ipAndPort : ipAndPorts) {
							String url = "http://" + (String) ipAndPort.get("ip") + ":" + ipAndPort.get("port");
							try {
								resp = Smlib.GetTopology(url);
								if (resp.status == HttpStatus.SC_OK) {
									JSONObject topologyInfo = JSONObject.parseObject(resp.content);
									if (topologyInfo != null) {
										JSONObject proxyUsers = topologyInfo.getJSONObject("proxy_users");
										if (proxyUsers != null) {
											for (Map.Entry<String, Object> user : proxyUsers.entrySet()) {
												Resp userResp = Smlib.GetUser(url, user.getKey());
												if (userResp.status != HttpStatus.SC_OK) {
													return RespJsonFactory.build(userResp.status,
															"调用swm用户接口异常：" + userResp.content);
												}

												JSONObject userInfo = JSONObject.parseObject(userResp.content);
												ServUserDto servUser = buildUserDto(userInfo);
												results.add(servUser);
											}
										}
									}
									break;
								}
							} catch (Exception e) {
							}
						}
						if (resp == null || resp.status != HttpStatus.SC_OK) {
							return RespJsonFactory.build(resp.status, "调用swm拓扑接口异常：" + resp.content);
						}
					}
				}
			}
			return RespJsonFactory.buildOK(results);
		} catch (

		Exception e) {
			logger.error("用户查询异常", e);
			throw new APIException("用户查询异常:" + e.getMessage());
		}
	}

	/**
	 * 用户详情
	 * 
	 * @param servId
	 *            服务编码
	 * @param username
	 *            用户名
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson get(String servId, String username) throws APIException {
		try {
			// 获取指定服务
			ServEntity serv = servDao.getBase(servId);
			if (serv == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "服务不存在");
			}

			// 服务类型
			String servType = serv.getOrder().getDefinitionServ().getName();
			if (!SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
				return RespJsonFactory.build(HttpStatus.SC_BAD_REQUEST, "该类型服务无用户");
			}

			// 站点
			String siteId = serv.getOrder().getArea().getSite().getId();

			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				// 子服务类型
				String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
				// switch_manager
				if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
					if (StringUtils.isNotBlank(subServ.getRelateId())) {
						// 从MGM获取指定服务的地址
						List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId, subServ.getRelateId(),
								subServ.getSubOrder().getDefinitionSubServ().getPortKey());

						if (ipAndPorts.size() == 0) {
							return RespJsonFactory.build(HttpStatus.SC_GONE, "获取不到SWM地址");
						}

						Resp resp = null;
						for (Map<String, Object> ipAndPort : ipAndPorts) {
							String url = "http://" + (String) ipAndPort.get("ip") + ":" + ipAndPort.get("port");
							try {
								resp = Smlib.GetUser(url, username);
								if (resp.status == HttpStatus.SC_OK) {
									JSONObject userInfo = JSONObject.parseObject(resp.content);
									ServUserDto servUser = buildUserDto(userInfo);
									return RespJsonFactory.buildOK(servUser);
								}
							} catch (Exception e) {
							}
						}
						if (resp == null || resp.status != HttpStatus.SC_OK) {
							return RespJsonFactory.build(resp.status, "调用swm用户接口异常：" + resp.content);
						}
					}
				}
			}

			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			logger.error("用户获取异常", e);
			throw new APIException("用户获取异常:" + e.getMessage());
		}
	}

	/**
	 * 用户新增
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson save(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_ADD;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 用户新增检查
			CheckResult chkRS = servUserCheck.checkSave(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			String servId = (String) paramMap.get("servId");
			// 获取指定服务
			ServEntity serv = servDao.getBase(servId);
			if (serv == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "服务不存在");
			}

			// 服务类型
			String servType = serv.getOrder().getDefinitionServ().getName();
			if (!SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
				return RespJsonFactory.build(HttpStatus.SC_BAD_REQUEST, "该类型服务无用户");
			}

			// 站点
			String siteId = serv.getOrder().getArea().getSite().getId();

			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				// 子服务类型
				String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
				// switch_manager
				if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
					if (StringUtils.isNotBlank(subServ.getRelateId())) {
						// 从MGM获取指定服务的地址
						List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId, subServ.getRelateId(),
								subServ.getSubOrder().getDefinitionSubServ().getPortKey());

						if (ipAndPorts.size() == 0) {
							return RespJsonFactory.build(HttpStatus.SC_GONE, "获取不到SWM地址");
						}

						// 构建用户
						User user = buildSwmUser(paramMap);

						Resp resp = null;
						for (Map<String, Object> ipAndPort : ipAndPorts) {
							String url = "http://" + (String) ipAndPort.get("ip") + ":" + ipAndPort.get("port");
							try {
								resp = Smlib.AddUser(url, user);
								if (resp.status == HttpStatus.SC_CREATED || resp.status == HttpStatus.SC_OK) {
									break;
								}
							} catch (Exception e) {
							}
						}
						if (resp == null || resp.status != HttpStatus.SC_OK) {
							return RespJsonFactory.build(resp.status, "调用swm用户接口异常：" + resp.content);
						}
					}
				}
			}

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SERV_USER, operateAcion, (String) paramMap.get("username"),
					(String) paramMap.get("username"));

			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			logger.error("服务用户" + operateAcionText + "异常", e);
			throw new APIException("服务用户" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 用户编辑
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson update(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_UPDATE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 编辑时检查
			CheckResult chkRS = servUserCheck.checkUpdate(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			String servId = (String) paramMap.get("servId");
			// 获取指定服务
			ServEntity serv = servDao.getBase(servId);
			if (serv == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "服务不存在");
			}

			// 服务类型
			String servType = serv.getOrder().getDefinitionServ().getName();
			if (!SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
				return RespJsonFactory.build(HttpStatus.SC_BAD_REQUEST, "该类型服务无用户");
			}

			// 站点
			String siteId = serv.getOrder().getArea().getSite().getId();

			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				// 子服务类型
				String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
				// switch_manager
				if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
					if (StringUtils.isNotBlank(subServ.getRelateId())) {
						// 从MGM获取指定服务的地址
						List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId, subServ.getRelateId(),
								subServ.getSubOrder().getDefinitionSubServ().getPortKey());

						if (ipAndPorts.size() == 0) {
							return RespJsonFactory.build(HttpStatus.SC_GONE, "获取不到SWM地址");
						}

						// 构建用户
						User user = buildSwmUser(paramMap);

						Resp resp = null;
						for (Map<String, Object> ipAndPort : ipAndPorts) {
							String url = "http://" + (String) ipAndPort.get("ip") + ":" + ipAndPort.get("port");
							try {
								resp = Smlib.UpdateUser(url, user);
								if (resp.status == HttpStatus.SC_CREATED || resp.status == HttpStatus.SC_OK) {
									break;
								}
							} catch (Exception e) {
							}
						}
						if (resp == null || resp.status != HttpStatus.SC_OK) {
							return RespJsonFactory.build(resp.status, "调用swm用户接口异常：" + resp.content);
						}
					}
				}
			}

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SERV_USER, operateAcion, (String) paramMap.get("username"),
					(String) paramMap.get("username"));

			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			logger.error("服务用户" + operateAcionText + "异常", e);
			throw new APIException("服务用户" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 用户删除
	 * 
	 * @param servId
	 *            服务编码
	 * @param username
	 *            用户名
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson remove(String servId, String username) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_REMOVE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定服务
			ServEntity serv = servDao.getBase(servId);
			if (serv == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "服务不存在");
			}

			// 服务类型
			String servType = serv.getOrder().getDefinitionServ().getName();
			if (!SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
				return RespJsonFactory.build(HttpStatus.SC_BAD_REQUEST, "该类型服务无用户");
			}

			// 站点
			String siteId = serv.getOrder().getArea().getSite().getId();

			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				// 子服务类型
				String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
				// switch_manager
				if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
					if (StringUtils.isNotBlank(subServ.getRelateId())) {
						// 从MGM获取指定服务的地址
						List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId, subServ.getRelateId(),
								subServ.getSubOrder().getDefinitionSubServ().getPortKey());

						if (ipAndPorts.size() == 0) {
							return RespJsonFactory.build(HttpStatus.SC_GONE, "获取不到SWM地址");
						}

						// 构建用户
						User user = new User();
						user.setUserName(username);

						Resp resp = null;
						for (Map<String, Object> ipAndPort : ipAndPorts) {
							String url = "http://" + (String) ipAndPort.get("ip") + ":" + ipAndPort.get("port");
							try {
								resp = Smlib.DeleteUser(url, user);
								if (resp.status == HttpStatus.SC_CREATED || resp.status == HttpStatus.SC_OK) {
									break;
								}
							} catch (Exception e) {
							}
						}
						if (resp == null || resp.status != HttpStatus.SC_OK) {
							return RespJsonFactory.build(resp.status, "调用swm用户接口异常：" + resp.content);
						}
					}
				}
			}

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SERV_USER, operateAcion, username, username);

			return RespJsonFactory.buildNoContent();
		} catch (Exception e) {
			logger.error("服务用户" + operateAcionText + "异常", e);
			throw new APIException("服务用户" + operateAcionText + "异常" + e.getMessage());
		}
	}

	@SuppressWarnings("unchecked")
	private User buildSwmUser(Map<String, Object> paramMap) {
		User user = new User();
		if (paramMap.containsKey("model")) {
			String model = (String) paramMap.get("model");
			switch (model) {
			case DictConstants.MODEL_RW:
				user.setReadOnly(false);
				user.setRwSplit(false);
				user.setShard(false);
				break;
			case DictConstants.MODEL_RW_SPLIT:
				user.setReadOnly(false);
				user.setRwSplit(true);
				user.setShard(false);
				break;
			case DictConstants.MODEL_READ_ONLY:
				user.setReadOnly(true);
				user.setRwSplit(false);
				user.setShard(false);
				break;
			default:
				break;
			}
		}
		user.setUserName(StringUtils.trim((String) paramMap.get("username")));

		if (paramMap.containsKey("password")) {
			user.setPassword(StringUtils.trim((String) paramMap.get("password")));
		}

		if (paramMap.containsKey("whiteIps")) {
			List<String> whiteIps = (List<String>) paramMap.get("whiteIps");
			if (whiteIps.size() > 0) {
				user.setWhiteList(whiteIps.toArray(new String[whiteIps.size()]));
			}
		}

		if (paramMap.containsKey("blackIps")) {
			List<String> blackIps = (List<String>) paramMap.get("blackIps");
			if (blackIps.size() > 0) {
				user.setBlackList(blackIps.toArray(new String[blackIps.size()]));
			}
		}

		if (paramMap.containsKey("dbPrivileges")) {
			Map<String, Object> dbPrivileges = (Map<String, Object>) paramMap.get("dbPrivileges");
			Map<String, String[]> privileges = new HashMap<>();
			for (Map.Entry<String, Object> entry : dbPrivileges.entrySet()) {
				List<String> value = (List<String>) entry.getValue();
				privileges.put(entry.getKey(), value.toArray(new String[value.size()]));
			}
			user.setDbPrivileges(privileges);
		}

		return user;
	}

	/**
	 * 构建用户展示对象
	 * 
	 * @param userInfo
	 * @return
	 */
	private ServUserDto buildUserDto(JSONObject swmUserInfo) {
		if (swmUserInfo == null) {
			return null;
		}
		ServUserDto servUser = new ServUserDto();
		servUser.setUsername(swmUserInfo.getString("UserName"));
		boolean readOnly = swmUserInfo.getBooleanValue("ReadOnly");
		boolean rwSplit = swmUserInfo.getBooleanValue("RwSplit");
		boolean shard = swmUserInfo.getBooleanValue("Shard");
		if (!readOnly && !rwSplit && !shard) {
			servUser.setModel(DictConstants.MODEL_RW);
		} else if (!readOnly && rwSplit && !shard) {
			servUser.setModel(DictConstants.MODEL_RW_SPLIT);
		} else if (readOnly && !rwSplit && !shard) {
			servUser.setModel(DictConstants.MODEL_READ_ONLY);
		}
		servUser.setModelText(dictTypeCache.getTextFromCache(DictTypeConstants.USER_MODEL, servUser.getModel()));

		JSONArray whites = swmUserInfo.getJSONArray("WhiteList");
		if (whites != null) {
			List<String> whiteIps = new ArrayList<>(whites.size());
			servUser.setWhiteIps(whiteIps);
			for (int i = 0; i < whites.size(); i++) {
				whiteIps.add(whites.getString(i));
			}
		}

		JSONArray blacks = swmUserInfo.getJSONArray("BlackList");
		if (blacks != null) {
			List<String> blackIps = new ArrayList<>(blacks.size());
			servUser.setBlackIps(blackIps);
			for (int i = 0; i < blacks.size(); i++) {
				blackIps.add(blacks.getString(i));
			}
		}

		JSONObject dbPrivilegesInfo = swmUserInfo.getJSONObject("DbPrivilegesMap");
		if (dbPrivilegesInfo != null) {
			Map<String, List<String>> dbPrivileges = new HashMap<>();
			servUser.setDbPrivileges(dbPrivileges);
			for (Map.Entry<String, Object> map : dbPrivilegesInfo.entrySet()) {
				JSONArray privilegesInfo = (JSONArray) map.getValue();
				List<String> privileges = new ArrayList<>(privilegesInfo.size());
				dbPrivileges.put(map.getKey(), privileges);
				for (int i = 0; i < privilegesInfo.size(); i++) {
					privileges.add(privilegesInfo.getString(i));
				}
			}
		}
		return servUser;
	}

}
